import fs from 'fs-extra';
import path from 'path';
import cp from 'child_process';
import * as esbuild from 'esbuild';
import chokidar from 'chokidar';
import { fileURLToPath } from 'url';
import electron from 'electron';
import livereload from 'livereload';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

/**
 * @type {ChildProcess}
 */
let electronCP = null;
const liveServer = livereload.createServer({port: 35729});

// 打包主进程与创建index.html文件
const buildElectron = async () => {
    await esbuild.build({
        entryPoints: ['./master/index.ts'],
        outfile: './dist/master.js',
        platform: 'node',
        bundle: true,
        external: ['electron', 'got'],
        format: 'esm',
    });
    await fs.copy('./resources', './dist/resources');
    await fs.createFile('./dist/index.html', `
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Electron App</title>
            <link rel="stylesheet" href="./index.css" >
            <style>
                body {
                    overflow: hidden;
                }
            </style>
        </head>
        <body>
            <script>
                const script = document.createElement('script');
                script.src = 'http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1';
                document.body.appendChild(script);
            </script>
            <script src="./render.js"></script>
        </body>
        </html>
    `);
};

// 打包渲染进程
const buildRender = async () => {
    await esbuild.build({
        entryPoints: ['./render/index.ts'],
        outfile: './dist/render.js',
        platform: 'browser',
        bundle: true,
        external: ['fs', 'path'],
    });
};

const buildStyle = async () => {
    await fs.copy('./render/index.css', './dist/index.css');
};

// 打包preload
const buildPreload = async () => {
    await esbuild.build({
        entryPoints: ['./preload/index.ts'],
        outfile: './dist/preload.js',
        platform: 'node',
        bundle: true,
        external: ['electron'],
        format: 'cjs',
    });
};

// 启动Electron
const startElectron = () => {
    electronCP = cp.spawn(electron, [path.join(__dirname, 'dist/master.js')]);
    electronCP.stdout.on('data', (chunk) => {
        process.stdout.write(`[master] ${chunk}`);
    });
    electronCP.stderr.on('data', (chunk) => {
        process.stderr.write(`[master ERR] ${chunk}`);
    });
    electronCP.once('close', process.exit);
};

await buildElectron();
await buildPreload();
await buildRender();
await buildStyle();
startElectron();

chokidar.watch('./master').on('change', async () => {
    await buildElectron();
    electronCP.removeAllListeners();
    electronCP.once('exit', startElectron);
    electronCP.kill();
});

chokidar.watch('./render/index.ts').on('change', async () => {
    await buildRender();
    liveServer.refresh('/');
});

chokidar.watch('./render/index.css').on('change', async () => {
    await buildStyle();
    liveServer.refresh('/');
});

chokidar.watch('./preload').on('change', async () => {
    await buildPreload();
    liveServer.refresh('/');
});
